// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import work from 'webworkify-webpack';
import Logger from './Logger';
import getEvents from './tools/event';
import Util from './Util';
import BaseClass from './tools/baseClass';
import WebGLRenderer from './WebglRenderer';
import { CLOUD_PHONE_RATIO } from './config/commonConfig';

class CanvasPlayer extends BaseClass {
    constructor(options) {
        super(options);
        this.options = {...options};
        this.moduleInit = false;
        this.streamList = [];
        this.document = document;
        this.util = new Util();

        this.options.events = getEvents();
        this.setCanvas();
        this.setImagerPlayer();

        /* javascript-obfuscator:disable */
        this.videoDecoderWorker = work(require.resolve('./worker/VideoDecoder.js'));
        
        /* javascript-obfuscator:enable */
        this.videoDecoderWorker.addEventListener('message', this.eventMessageHandel.bind(this));
    }

    setCanvas () {
        const $canvas = this.util.createCanvas(this.options.isMobile, CLOUD_PHONE_RATIO);
        // 放入元素内部
        let parentNode = document.getElementById('container');
        parentNode.appendChild($canvas);
        this.canvas = $canvas;
    }

    setImagerPlayer () {
        const canvas = document.getElementById('playCanvas');
        this.webglPlayer = new WebGLRenderer(canvas, {
            preserveDrawingBuffer: false
        });
    }

    loadjs(decoderType) {
        if (!decoderType) {
            decoderType = 'H264';
        }
        this.videoDecoderWorker.postMessage({
          type: 'loadwasm',
          libPath: this.options.libPath,
          decoderType
        })
    }
    
    eventMessageHandel(event) {
        let workerData = event.data
        let type = workerData.type
        let data = workerData.data
        switch (type) {
          case 'decoded':
            this.onRenderImage(data);
            break
          case 'decoderReady':
            this.moduleInit = true;
            break;
        }
    }

    onRenderImage(obj) {
      let unData = new Uint8Array(obj.data);
      let width = obj.width;
      let height = obj.height;
      let yLength = width * height;
      let uvLength = (width / 2) * (height / 2);
      if(!this.webglPlayer) {
        this.setImagerPlayer();
      }
      this.webglPlayer.renderFrame(unData, width, height, yLength, uvLength);
    }

    startDecod() {
      const streamData = this.streamList.shift();
      if (streamData && streamData.buffer) {
        this.videoDecoderWorker.postMessage({
          type: 'startDecode',
          data: streamData
        }, [streamData.buffer])
      } else {
          Logger.error('startDecode', 'data is null', 'data:', data)
      }
    }

    messageHandler(evt) {
        const message = evt.data;
        if (!Object.prototype.hasOwnProperty.call(message, 'type')) {
            return;
        }

        switch (message.type) {
            // worker 中 onHeadersReady 被调用时触发
            case 'pictureParams': {
                const croppingParams = message.croppingParams;
                if (croppingParams === null) {
                    this.canvas.width = message.width;
                    this.canvas.height = message.height;
                } else {
                    this.canvas.width = croppingParams.width;
                    this.canvas.height = croppingParams.height;
                }

                break;
            }

            // worker 中 onPictureReady 被调用时触发
            case 'pictureReady':
                /*global __IS_DEBUG__*/
                if (__IS_DEBUG__) {
                    let traceId = window.delayAnalysis.shiftTraceId('decode');
                    window.delayAnalysis.record(['decode', 'end', traceId]);
                }

                this.h264bsdCanvas.drawNextOutputPicture(
                    message.width,
                    message.height,
                    message.croppingParams,
                    new Uint8Array(message.data)
                );
                break;

            // 当前队列中所有数据被处理完后触发
            case 'noInput':
                break;

            // decode 方法返回错误码
            case 'decodeError':
            case 'paramSetError':
            case 'memAllocError':
                Logger.debug('Decoder error: ' + message.type);
                break;

            default:
                // do nothing
        }
    }

    decode(data) {
        /*global __IS_DEBUG__*/
        if (__IS_DEBUG__) {
            let traceId = window.delayAnalysis.shiftTraceId('receive') || '';
            window.delayAnalysis.cacheTraceId('decode', traceId);
            window.delayAnalysis.record(['decode', 'start', traceId]);
        }

        // 暂存流数据，等解码器准备好后开始解码
        this.streamList.push(data);
        if (this.moduleInit) {
          this.startDecod();
        }
    }

    destroy() {
        this.videoDecoderWorker.terminate();
    }
}

export default CanvasPlayer;
